{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "4a6ab9a2-28a2-445d-8512-a0dc8d1b54e9",
   "metadata": {},
   "source": [
    "# Code Generator\n",
    "\n",
    "The requirement: use an Open Source model to generate high performance C++ code from Python code\n",
    "\n",
    "To replicate this, you'll need to set up a HuggingFace endpoint as I do in the video. It's simple to do, and it's quite satisfying to see the results!\n",
    "\n",
    "It's also an important part of your learning; this is the first example of deploying an open source model to be behind an API. We'll return to this in Week 8, but this should plant a seed in your mind for what's involved in moving open source models into production."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22e1567b-33fd-49e7-866e-4b635d15715a",
   "metadata": {},
   "source": [
    "<table style=\"margin: 0; text-align: left;\">\n",
    "    <tr>\n",
    "        <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n",
    "            <img src=\"../important.jpg\" width=\"150\" height=\"150\" style=\"display: block;\" />\n",
    "        </td>\n",
    "        <td>\n",
    "            <h1 style=\"color:#900;\">Important - Pause Endpoints when not in use</h1>\n",
    "            <span style=\"color:#900;\">\n",
    "            If you do decide to use HuggingFace endpoints for this project, you should stop or pause the endpoints when you are done to avoid accruing unnecessary running cost. The costs are very low as long as you only run the endpoint when you're using it. Navigate to the HuggingFace endpoint UI <a href=\"https://ui.endpoints.huggingface.co/\">here,</a> open your endpoint, and click Pause to put it on pause so you no longer pay for it.  \n",
    "Many thanks to student John L. for raising this.\n",
    "<br/><br/>\n",
    "In week 8 we will use Modal instead of HuggingFace endpoints; with Modal you only pay for the time that you use it and you should get free credits.\n",
    "            </span>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e610bf56-a46e-4aff-8de1-ab49d62b1ad3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# imports\n",
    "\n",
    "import os\n",
    "import io\n",
    "import sys\n",
    "import json\n",
    "import requests\n",
    "from dotenv import load_dotenv\n",
    "from openai import OpenAI\n",
    "import google.generativeai\n",
    "import anthropic\n",
    "from IPython.display import Markdown, display, update_display\n",
    "import gradio as gr\n",
    "import subprocess"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4f672e1c-87e9-4865-b760-370fa605e614",
   "metadata": {},
   "outputs": [],
   "source": [
    "# environment\n",
    "\n",
    "load_dotenv()\n",
    "os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY', 'your-key-if-not-using-env')\n",
    "os.environ['ANTHROPIC_API_KEY'] = os.getenv('ANTHROPIC_API_KEY', 'your-key-if-not-using-env')\n",
    "os.environ['HF_TOKEN'] = os.getenv('HF_TOKEN', 'your-key-if-not-using-env')\n",
    "\n",
    "if os.environ['HF_TOKEN'] == 'your-key-if-not-using-env':\n",
    "    print(\"Failed to load token, is it inside your .env file?\")\n",
    "else:\n",
    "    print(f\"Successfully loaded token beginning {os.environ['HF_TOKEN'][:5]}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8aa149ed-9298-4d69-8fe2-8f5de0f667da",
   "metadata": {},
   "outputs": [],
   "source": [
    "# initialize\n",
    "\n",
    "openai = OpenAI()\n",
    "claude = anthropic.Anthropic()\n",
    "hf_inference_provider = OpenAI(base_url=\"https://api-inference.huggingface.co/v1/\", api_key=os.environ['HF_TOKEN'])\n",
    "OPENAI_MODEL = \"gpt-4o\"\n",
    "CLAUDE_MODEL = \"claude-3-5-sonnet-20240620\""
   ]
  },
  {
   "attachments": {
    "feb6838c-7764-4a7e-bd70-d76e0ab3dda6.png": {
     "image/png": "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Y6PGWOdEP2PZRJNoRIVf0hAYNepIH29ocx5+eBKNHHkk3XXXPfTeex/4wsWxaRFISYnt6A8IVx06dKArrxxHzzzzJGGZQn2n119/w1eFJUuWivDoQ0QcdQkBfVRPXSpR8svSGOucaFRFA5loRIVf0hDAujKbsB7s2WefV16vvTbFDhJ7PUWgV6+edP/999C5515QT2ugi/3KK6/SX3/9RQccsD9v8PqTXn75lXpdHyl8Q0cgto+9hoVCY6xzYp+gCJCJxVO4JREBe60lspkz5/sk5iasE43Azz//Qpdeepli27ZtO+rcuRPtt98ItSHK1jpuv/121LFjB8KmqPpMM2Z8S/gTEgQEAUGgISIgAmRDfKp1rE6bbbaZW6Jly5a5GwmaN8+jESOG04AB/XlDxe/09dff0IIFC924tqVJkyYU3EAAt+G9bt06dZyPnQb2rl270J577kHdunXj3bAFtGjRYvrgg6k8nbguGNV1G57wMOXFcSyHHz6SttxySyopKab3359K3303x01jLInKD/yqg4/J35iZmZmM7T68ZrQntWzZin799VeFL7S20agm5Y/Gzw7DcTYGd5jz58+njz/+hCAwPvDAvWRPee+//370+ONPusnjeSbt27envffek7p3767yQBv49NNP6Z9//nX52xbsnDYn5ZaVldLy5SvsYJ+9Xbu2lJ6e4fotX77cPbbHLnNxcbFa5+lGDFjatm2r+kLPnj1UvK+++pq+/34ubzCq3hFAEMT32WcY9e/fT21uW7JkieLzzTczAjl6TrSzpk1zlUdBwUb3GfXt21cJ+Hl5zeinn34mrG/GjnJD2CS14447UO/evblvpqoPOpTbPGMTT8yGicAtt99E7dq3peLiErro/EuohE1DJ51yAg0ZuptqC5deqD8ad95lJzrjrNNMlBDz6+nf0BOPPUUTH3tItafZs+bQww9OdONdde0V1L1HN1rw50K65cbbXP9zzjuLth+4Ha1csZIuH3uV6y+W5CMgAmTyMW7UOZxwwnF09tlnuhicfvqZLEBW0p133k6tWnkLt4cN25vGjDlbbYS54oqr3fiwTJv2Hr/gmvr84Bg58hD1B/vbb79Lt956O6yKMN2NPLp06WK8XPP888+lL7+cTuPGXen6GUuwvCeddJoSXCdNmkBYq2dowIABdOyxJxgnJSq/muDjFoItublN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BfKfpYv80mQ4CZAACZAACZAACZBANSCQ36C5Zy1ogfTEwkASIAESIAESIAESIAE/AlQg/cgwnARIgARIgARIgARIwJMAFUhPLAwkARIgARIgARIgARLwI0AF0o8Mw0mABEiABEiABEiABDwJUIH0xMJAEiABEiABEiABEiABPwJUIP3IMJwESIAESIAESIAESMCTABVITywMJAESIAESIAESIAES8CNABdKPDMNJgARIgARIgARIgAQ8CVCB9MTCQBIgARIgARIgARIgAT8CVCD9yDCcBEiABEiABEiABEjAkwAVSE8sDCQBEiABEiABEiABEvAjQAXSjwzDSYAESIAESIAESIAEPAlQgfTEwkASIAESIAESIAESIAE/AlQg/cgwnARIgARIgARIgARIwJMAFUhPLAwkARIgARIgARIgARLwI5DrdyBTw7OyslRObm2VnVNLZWfnqqzsbJWVRT05U9uT5SYBEiABEiCB6kagtLRElZaUqJKSIlVSXKiKizap0tLSjKpmtVEgoSzm5tVVubXqZFQDsLAkQAIkQAIkQAI1iwAMW1k52drYpdUwo7c0UEWFG1XR5g1GqcwEGtVCgaxVu56qlZfv8DaaPbR7rc2HNPrM0uqdinCHBEiABEiABEigGhLI0r2j8hfqKYUBDH+FmwtU4ab1aV/njFYgYXXMq9MgpMFr1CUlxVphxB8VxrS/8lhAEiABEiABEqixBEIGrpC6UlymTObooXc5xiCWk5OnNm9cm9bWyIwdHIgxjrXzGxnlEQpjsR5DgLEEVB5r7N3IipMACZAACZBARhKA7gIdBroM9tG1HdJxaqVtfTJSgYTlsXbdhmZyDLqri4s3a+AlaQuZBSMBEiABEiABEiCBWARsnQbjJKHrQOdJR8lIBRLd1gAbAl2YjlxZJhIgARIgARIgARJIikDIEllidB3oPOkoGadAYsIMTLvSbZ2OUFkmEiABEiABEiABEqgIAbs7G7pPuklGKZAw48psa4wVoJAACZAACZAACZBAdSUgug50n3Trys4oBRJ+HiGh2dYc81hdbxjWiwRIgARIgARIQJmhetB5IKIDpQuXjFEg4S9JnITDVQ+FBEiABEiABEiABKo7AdF5oANBF0oXyRgFEssTQjBxhq560uXyYTlIgARIgARIgARSSQA6j3iaEV0olfnFm3bGKJDw+wgR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"
    }
   },
   "cell_type": "markdown",
   "id": "99291840-3009-46b6-b663-f250a0b547cb",
   "metadata": {},
   "source": [
    "# New - use Huggingface Provided Inference Endpoint for free - use DEEPSEEK!\n",
    "* if available, Huggingface is providing their own inference endpoints to some of their models.\n",
    "* this may change over time, but currently, the below deepseek model is one such model.\n",
    "* usage is included in the free account limits, so there is no cost unlike the HF Inference Endpoints discussed in day 4.\n",
    "\n",
    "![image.png](attachment:feb6838c-7764-4a7e-bd70-d76e0ab3dda6.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3498faf0-8c08-4d1a-b995-9c4ef406be4b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# endpoint for which this is available from the huggingface site and deploy dropdown\n",
    "DEEPSEEK_MODEL = \"deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6896636f-923e-4a2c-9d6c-fac07828a201",
   "metadata": {},
   "outputs": [],
   "source": [
    "system_message = \"You are an assistant that reimplements Python code in high performance C++ for an M1 Mac. \"\n",
    "system_message += \"Respond only with C++ code; use comments sparingly and do not provide any explanation other than occasional comments. \"\n",
    "system_message += \"The C++ response needs to produce an identical output in the fastest possible time. Keep implementations of random number generators identical so that results match exactly.\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8e7b3546-57aa-4c29-bc5d-f211970d04eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "def user_prompt_for(python):\n",
    "    user_prompt = \"Rewrite this Python code in C++ with the fastest possible implementation that produces identical output in the least time. \"\n",
    "    user_prompt += \"Respond only with C++ code; do not explain your work other than a few comments. \"\n",
    "    user_prompt += \"Pay attention to number types to ensure no int overflows. Remember to #include all necessary C++ packages such as iomanip.\\n\\n\"\n",
    "    user_prompt += python\n",
    "    return user_prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c6190659-f54c-4951-bef4-4960f8e51cc4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def messages_for(python):\n",
    "    return [\n",
    "        {\"role\": \"system\", \"content\": system_message},\n",
    "        {\"role\": \"user\", \"content\": user_prompt_for(python)}\n",
    "    ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71e1ba8c-5b05-4726-a9f3-8d8c6257350b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# write to a file called optimized.cpp\n",
    "\n",
    "def write_output(cpp):\n",
    "    code = cpp.replace(\"```cpp\",\"\").replace(\"```\",\"\")\n",
    "    with open(\"optimized.cpp\", \"w\") as f:\n",
    "        f.write(code)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e7d2fea8-74c6-4421-8f1e-0e76d5b201b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def optimize_gpt(python):    \n",
    "    stream = openai.chat.completions.create(model=OPENAI_MODEL, messages=messages_for(python), stream=True)\n",
    "    reply = \"\"\n",
    "    for chunk in stream:\n",
    "        fragment = chunk.choices[0].delta.content or \"\"\n",
    "        reply += fragment\n",
    "        print(fragment, end='', flush=True)\n",
    "    write_output(reply)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7cd84ad8-d55c-4fe0-9eeb-1895c95c4a9d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def optimize_claude(python):\n",
    "    result = claude.messages.stream(\n",
    "        model=CLAUDE_MODEL,\n",
    "        max_tokens=2000,\n",
    "        system=system_message,\n",
    "        messages=[{\"role\": \"user\", \"content\": user_prompt_for(python)}],\n",
    "    )\n",
    "    reply = \"\"\n",
    "    with result as stream:\n",
    "        for text in stream.text_stream:\n",
    "            reply += text\n",
    "            print(text, end=\"\", flush=True)\n",
    "    write_output(reply)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1bcd63f-0c97-420a-9fe1-c573283a9b7e",
   "metadata": {},
   "source": [
    "# New function to serve HF Inference Provider model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8047295c-ec4a-489c-8dad-79db73a2dfca",
   "metadata": {},
   "outputs": [],
   "source": [
    "def optimize_hf_inference_provider(python):    \n",
    "    stream = hf_inference_provider.chat.completions.create(model=DEEPSEEK_MODEL, messages=messages_for(python), max_tokens=500, stream=True)\n",
    "    reply = \"\"\n",
    "    for chunk in stream:\n",
    "        fragment = chunk.choices[0].delta.content or \"\"\n",
    "        reply += fragment\n",
    "        print(fragment, end='', flush=True)\n",
    "    write_output(reply)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a1cbb778-fa57-43de-b04b-ed523f396c38",
   "metadata": {},
   "outputs": [],
   "source": [
    "pi = \"\"\"\n",
    "import time\n",
    "\n",
    "def calculate(iterations, param1, param2):\n",
    "    result = 1.0\n",
    "    for i in range(1, iterations+1):\n",
    "        j = i * param1 - param2\n",
    "        result -= (1/j)\n",
    "        j = i * param1 + param2\n",
    "        result += (1/j)\n",
    "    return result\n",
    "\n",
    "start_time = time.time()\n",
    "result = calculate(100_000_000, 4, 1) * 4\n",
    "end_time = time.time()\n",
    "\n",
    "print(f\"Result: {result:.12f}\")\n",
    "print(f\"Execution Time: {(end_time - start_time):.6f} seconds\")\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7fe1cd4b-d2c5-4303-afed-2115a3fef200",
   "metadata": {},
   "outputs": [],
   "source": [
    "exec(pi)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "105db6f9-343c-491d-8e44-3a5328b81719",
   "metadata": {},
   "outputs": [],
   "source": [
    "optimize_gpt(pi)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf26ee95-0c77-491d-9a91-579a1e96a8a3",
   "metadata": {},
   "outputs": [],
   "source": [
    "exec(pi)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4194e40c-04ab-4940-9d64-b4ad37c5bb40",
   "metadata": {},
   "outputs": [],
   "source": [
    "!clang++ -O3 -std=c++17 -march=armv8.3-a -o optimized optimized.cpp\n",
    "!./optimized"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "983a11fe-e24d-4c65-8269-9802c5ef3ae6",
   "metadata": {},
   "outputs": [],
   "source": [
    "optimize_claude(pi)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5a766f9-3d23-4bb4-a1d4-88ec44b61ddf",
   "metadata": {},
   "outputs": [],
   "source": [
    "!clang++ -O3 -std=c++17 -march=armv8.3-a -o optimized optimized.cpp\n",
    "!./optimized"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3b497b3-f569-420e-b92e-fb0f49957ce0",
   "metadata": {},
   "outputs": [],
   "source": [
    "python_hard = \"\"\"# Be careful to support large number sizes\n",
    "\n",
    "def lcg(seed, a=1664525, c=1013904223, m=2**32):\n",
    "    value = seed\n",
    "    while True:\n",
    "        value = (a * value + c) % m\n",
    "        yield value\n",
    "        \n",
    "def max_subarray_sum(n, seed, min_val, max_val):\n",
    "    lcg_gen = lcg(seed)\n",
    "    random_numbers = [next(lcg_gen) % (max_val - min_val + 1) + min_val for _ in range(n)]\n",
    "    max_sum = float('-inf')\n",
    "    for i in range(n):\n",
    "        current_sum = 0\n",
    "        for j in range(i, n):\n",
    "            current_sum += random_numbers[j]\n",
    "            if current_sum > max_sum:\n",
    "                max_sum = current_sum\n",
    "    return max_sum\n",
    "\n",
    "def total_max_subarray_sum(n, initial_seed, min_val, max_val):\n",
    "    total_sum = 0\n",
    "    lcg_gen = lcg(initial_seed)\n",
    "    for _ in range(20):\n",
    "        seed = next(lcg_gen)\n",
    "        total_sum += max_subarray_sum(n, seed, min_val, max_val)\n",
    "    return total_sum\n",
    "\n",
    "# Parameters\n",
    "n = 10000         # Number of random numbers\n",
    "initial_seed = 42 # Initial seed for the LCG\n",
    "min_val = -10     # Minimum value of random numbers\n",
    "max_val = 10      # Maximum value of random numbers\n",
    "\n",
    "# Timing the function\n",
    "import time\n",
    "start_time = time.time()\n",
    "result = total_max_subarray_sum(n, initial_seed, min_val, max_val)\n",
    "end_time = time.time()\n",
    "\n",
    "print(\"Total Maximum Subarray Sum (20 runs):\", result)\n",
    "print(\"Execution Time: {:.6f} seconds\".format(end_time - start_time))\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dab5e4bc-276c-4555-bd4c-12c699d5e899",
   "metadata": {},
   "outputs": [],
   "source": [
    "exec(python_hard)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e8d24ed5-2c15-4f55-80e7-13a3952b3cb8",
   "metadata": {},
   "outputs": [],
   "source": [
    "optimize_gpt(python_hard)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0b3d073-88a2-40b2-831c-6f0c345c256f",
   "metadata": {},
   "outputs": [],
   "source": [
    "!clang++ -O3 -std=c++17 -march=armv8.3-a -o optimized optimized.cpp\n",
    "!./optimized"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e9305446-1d0c-4b51-866a-b8c1e299bf5c",
   "metadata": {},
   "outputs": [],
   "source": [
    "optimize_claude(python_hard)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c181036-8193-4fdd-aef3-fc513b218d43",
   "metadata": {},
   "outputs": [],
   "source": [
    "!clang++ -O3 -std=c++17 -march=armv8.3-a -o optimized optimized.cpp\n",
    "!./optimized"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0be9f47d-5213-4700-b0e2-d444c7c738c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "def stream_gpt(python):    \n",
    "    stream = openai.chat.completions.create(model=OPENAI_MODEL, messages=messages_for(python), stream=True)\n",
    "    reply = \"\"\n",
    "    for chunk in stream:\n",
    "        fragment = chunk.choices[0].delta.content or \"\"\n",
    "        reply += fragment\n",
    "        yield reply.replace('```cpp\\n','').replace('```','')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14647d36-ab11-4d06-9619-0a45761e8488",
   "metadata": {},
   "source": [
    "def stream_claude(python):\n",
    "    result = claude.messages.stream(\n",
    "        model=CLAUDE_MODEL,\n",
    "        max_tokens=2000,\n",
    "        system=system_message,\n",
    "        messages=[{\"role\": \"user\", \"content\": user_prompt_for(python)}],\n",
    "    )\n",
    "    reply = \"\"\n",
    "    with result as stream:\n",
    "        for text in stream.text_stream:\n",
    "            reply += text\n",
    "            yield reply.replace('```cpp\\n','').replace('```','')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e6aecc8c-87d2-4b8c-8335-58359464eaa0",
   "metadata": {},
   "source": [
    "# New function to serve HF Inference Provider model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fcb30458-1023-41d7-bc9a-7e95d5e782aa",
   "metadata": {},
   "outputs": [],
   "source": [
    "def stream_hf_inference_provider(python):    \n",
    "    stream = hf_inference_provider.chat.completions.create(model=DEEPSEEK_MODEL, messages=messages_for(python), max_tokens=500, stream=True)\n",
    "    reply = \"\"\n",
    "    for chunk in stream:\n",
    "        fragment = chunk.choices[0].delta.content or \"\"\n",
    "        reply += fragment\n",
    "        yield reply.replace('```cpp\\n','').replace('```','')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2f1ae8f5-16c8-40a0-aa18-63b617df078d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def optimize(python, model):\n",
    "    if model==\"GPT\":\n",
    "        result = stream_gpt(python)\n",
    "    elif model==\"Claude\":\n",
    "        result = stream_claude(python)\n",
    "    elif model==\"HF Inference Model\":\n",
    "        result = stream_hf_inference_provider(python)\n",
    "    else:\n",
    "        raise ValueError(\"Unknown model\")\n",
    "    for stream_so_far in result:\n",
    "        yield stream_so_far        "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53775d39-d96e-4e63-b68a-e995860a1d44",
   "metadata": {},
   "source": [
    "# Updated so you can now run DEEPSEEK!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f1ddb38e-6b0a-4c37-baa4-ace0b7de887a",
   "metadata": {},
   "outputs": [],
   "source": [
    "with gr.Blocks() as ui:\n",
    "    with gr.Row():\n",
    "        python = gr.Textbox(label=\"Python code:\", lines=10, value=python_hard)\n",
    "        cpp = gr.Textbox(label=\"C++ code:\", lines=10)\n",
    "    with gr.Row():\n",
    "        model = gr.Dropdown([\"GPT\", \"Claude\", \"HF Inference Model\"], label=\"Select model\", value=\"GPT\")\n",
    "        convert = gr.Button(\"Convert code\")\n",
    "\n",
    "    convert.click(optimize, inputs=[python, model], outputs=[cpp])\n",
    "\n",
    "ui.launch(inbrowser=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19bf2bff-a822-4009-a539-f003b1651383",
   "metadata": {},
   "outputs": [],
   "source": [
    "def execute_python(code):\n",
    "    try:\n",
    "        output = io.StringIO()\n",
    "        sys.stdout = output\n",
    "        exec(code)\n",
    "    finally:\n",
    "        sys.stdout = sys.__stdout__\n",
    "    return output.getvalue()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "77f3ab5d-fcfb-4d3f-8728-9cacbf833ea6",
   "metadata": {},
   "outputs": [],
   "source": [
    "def execute_cpp(code):\n",
    "    write_output(code)\n",
    "    try:\n",
    "        compile_result = subprocess.run(compiler_cmd[2], check=True, text=True, capture_output=True)\n",
    "        run_cmd = [\"./optimized\"]\n",
    "        run_result = subprocess.run(run_cmd, check=True, text=True, capture_output=True)\n",
    "        return run_result.stdout\n",
    "    except subprocess.CalledProcessError as e:\n",
    "        return f\"An error occurred:\\n{e.stderr}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9a2274f1-d03b-42c0-8dcc-4ce159b18442",
   "metadata": {},
   "outputs": [],
   "source": [
    "css = \"\"\"\n",
    ".python {background-color: #306998;}\n",
    ".cpp {background-color: #050;}\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "409feaac-9c0a-40ff-b1b9-536878dcab82",
   "metadata": {},
   "source": [
    "# Updated so you can now run DEEPSEEK!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f1303932-160c-424b-97a8-d28c816721b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "with gr.Blocks(css=css) as ui:\n",
    "    gr.Markdown(\"## Convert code from Python to C++\")\n",
    "    with gr.Row():\n",
    "        python = gr.Textbox(label=\"Python code:\", value=python_hard, lines=10)\n",
    "        cpp = gr.Textbox(label=\"C++ code:\", lines=10)\n",
    "    with gr.Row():\n",
    "        model = gr.Dropdown([\"GPT\", \"Claude\", \"HF Inference Model\"], label=\"Select model\", value=\"GPT\")\n",
    "    with gr.Row():\n",
    "        convert = gr.Button(\"Convert code\")\n",
    "    with gr.Row():\n",
    "        python_run = gr.Button(\"Run Python\")\n",
    "        cpp_run = gr.Button(\"Run C++\")\n",
    "    with gr.Row():\n",
    "        python_out = gr.TextArea(label=\"Python result:\", elem_classes=[\"python\"])\n",
    "        cpp_out = gr.TextArea(label=\"C++ result:\", elem_classes=[\"cpp\"])\n",
    "\n",
    "    convert.click(optimize, inputs=[python, model], outputs=[cpp])\n",
    "    python_run.click(execute_python, inputs=[python], outputs=[python_out])\n",
    "    cpp_run.click(execute_cpp, inputs=[cpp], outputs=[cpp_out])\n",
    "\n",
    "ui.launch(inbrowser=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb8c5b4e-ec51-4f21-b3f8-6aa94fede86d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from huggingface_hub import login, InferenceClient\n",
    "from transformers import AutoTokenizer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13347633-4606-4e38-9927-80c39e65c1f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "hf_token = os.environ['HF_TOKEN']\n",
    "login(hf_token, add_to_git_credential=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ef60a4df-6267-4ebd-8eed-dcb917af0a5e",
   "metadata": {},
   "outputs": [],
   "source": [
    "code_qwen = \"Qwen/CodeQwen1.5-7B-Chat\"\n",
    "code_gemma = \"google/codegemma-7b-it\"\n",
    "CODE_QWEN_URL = \"https://h1vdol7jxhje3mpn.us-east-1.aws.endpoints.huggingface.cloud\"\n",
    "CODE_GEMMA_URL = \"https://c5hggiyqachmgnqg.us-east-1.aws.endpoints.huggingface.cloud\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "695ce389-a903-4533-a2f1-cd9e2a6af8f2",
   "metadata": {},
   "outputs": [],
   "source": [
    "tokenizer = AutoTokenizer.from_pretrained(code_qwen)\n",
    "messages = messages_for(pi)\n",
    "text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d4548e96-0b32-4793-bdd6-1b072c2f26ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb2a126b-09e7-4966-bc97-0ef5c2cc7896",
   "metadata": {},
   "outputs": [],
   "source": [
    "client = InferenceClient(CODE_QWEN_URL, token=hf_token)\n",
    "stream = client.text_generation(text, stream=True, details=True, max_new_tokens=3000)\n",
    "for r in stream:\n",
    "    print(r.token.text, end = \"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c032ad4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "127a52e5-ad85-42b7-a0f5-9afda5efe090",
   "metadata": {},
   "outputs": [],
   "source": [
    "def stream_hf_inference_provider(python):\n",
    "    tokenizer = AutoTokenizer.from_pretrained(code_qwen)\n",
    "    messages = messages_for(python)\n",
    "    text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)\n",
    "    client = InferenceClient(CODE_QWEN_URL, token=hf_token)\n",
    "    stream = client.text_generation(text, stream=True, details=True, max_new_tokens=3000)\n",
    "    result = \"\"\n",
    "    for r in stream:\n",
    "        result += r.token.text\n",
    "        yield result    \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a82387d1-7651-4923-995b-fe18356fcaa6",
   "metadata": {},
   "outputs": [],
   "source": [
    "def optimize(python, model):\n",
    "    if model==\"GPT\":\n",
    "        result = stream_gpt(python)\n",
    "    elif model==\"Claude\":\n",
    "        result = stream_claude(python)\n",
    "    elif model==\"HF Inference Model\":\n",
    "        result = stream_hf_inference_provider(python)\n",
    "    else:\n",
    "        raise ValueError(\"Unknown model\")\n",
    "    for stream_so_far in result:\n",
    "        yield stream_so_far    "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b0a6a97-5b8a-4a9b-8ee0-7561e0ced673",
   "metadata": {},
   "source": [
    "<table style=\"margin: 0; text-align: left;\">\n",
    "    <tr>\n",
    "        <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n",
    "            <img src=\"../thankyou.jpg\" width=\"150\" height=\"150\" style=\"display: block;\" />\n",
    "        </td>\n",
    "        <td>\n",
    "            <h2 style=\"color:#090;\">Thank you to @CloudLlama for an amazing contribution</h2>\n",
    "            <span style=\"color:#090;\">\n",
    "                A student has contributed a chunk of code to improve this, in the next 2 cells. You can now select which Python porgram to run,\n",
    "                and a compiler is automatically selected that will work on PC, Windows and Mac. Massive thank you @CloudLlama!\n",
    "            </span>\n",
    "        </td>\n",
    "    </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4ba311ec-c16a-4fe0-946b-4b940704cf65",
   "metadata": {},
   "outputs": [],
   "source": [
    "def select_sample_program(sample_program):\n",
    "    if sample_program==\"pi\":\n",
    "        return pi\n",
    "    elif sample_program==\"python_hard\":\n",
    "        return python_hard\n",
    "    else:\n",
    "        return \"Type your Python program here\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e42286bc-085c-45dc-b101-234308e58269",
   "metadata": {},
   "outputs": [],
   "source": [
    "import platform\n",
    "\n",
    "VISUAL_STUDIO_2022_TOOLS = \"C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\Common7\\Tools\\\\VsDevCmd.bat\"\n",
    "VISUAL_STUDIO_2019_TOOLS = \"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\Common7\\\\Tools\\\\VsDevCmd.bat\"\n",
    "\n",
    "simple_cpp = \"\"\"\n",
    "#include <iostream>\n",
    "\n",
    "int main() {\n",
    "    std::cout << \"Hello\";\n",
    "    return 0;\n",
    "}\n",
    "\"\"\"\n",
    "\n",
    "def run_cmd(command_to_run):\n",
    "    try:\n",
    "        run_result = subprocess.run(command_to_run, check=True, text=True, capture_output=True)\n",
    "        return run_result.stdout if run_result.stdout else \"SUCCESS\"\n",
    "    except:\n",
    "        return \"\"\n",
    "\n",
    "def c_compiler_cmd(filename_base):\n",
    "    my_platform = platform.system()\n",
    "    my_compiler = []\n",
    "\n",
    "    try:\n",
    "        with open(\"simple.cpp\", \"w\") as f:\n",
    "            f.write(simple_cpp)\n",
    "            \n",
    "        if my_platform == \"Windows\":\n",
    "            if os.path.isfile(VISUAL_STUDIO_2022_TOOLS):\n",
    "                if os.path.isfile(\"./simple.exe\"):\n",
    "                    os.remove(\"./simple.exe\")\n",
    "                compile_cmd = [\"cmd\", \"/c\", VISUAL_STUDIO_2022_TOOLS, \"&\", \"cl\", \"simple.cpp\"]\n",
    "                if run_cmd(compile_cmd):\n",
    "                    if run_cmd([\"./simple.exe\"]) == \"Hello\":\n",
    "                        my_compiler = [\"Windows\", \"Visual Studio 2022\", [\"cmd\", \"/c\", VISUAL_STUDIO_2022_TOOLS, \"&\", \"cl\", f\"{filename_base}.cpp\"]]\n",
    "        \n",
    "            if not my_compiler:\n",
    "                if os.path.isfile(VISUAL_STUDIO_2019_TOOLS):\n",
    "                    if os.path.isfile(\"./simple.exe\"):\n",
    "                        os.remove(\"./simple.exe\")\n",
    "                    compile_cmd = [\"cmd\", \"/c\", VISUAL_STUDIO_2019_TOOLS, \"&\", \"cl\", \"simple.cpp\"]\n",
    "                    if run_cmd(compile_cmd):\n",
    "                        if run_cmd([\"./simple.exe\"]) == \"Hello\":\n",
    "                            my_compiler = [\"Windows\", \"Visual Studio 2019\", [\"cmd\", \"/c\", VISUAL_STUDIO_2019_TOOLS, \"&\", \"cl\", f\"{filename_base}.cpp\"]]\n",
    "    \n",
    "            if not my_compiler:\n",
    "                my_compiler=[my_platform, \"Unavailable\", []]\n",
    "                \n",
    "        elif my_platform == \"Linux\":\n",
    "            if os.path.isfile(\"./simple\"):\n",
    "                os.remove(\"./simple\")\n",
    "            compile_cmd = [\"g++\", \"simple.cpp\", \"-o\", \"simple\"]\n",
    "            if run_cmd(compile_cmd):\n",
    "                if run_cmd([\"./simple\"]) == \"Hello\":\n",
    "                    my_compiler = [\"Linux\", \"GCC (g++)\", [\"g++\", f\"{filename_base}.cpp\", \"-o\", f\"{filename_base}\" ]]\n",
    "    \n",
    "            if not my_compiler:\n",
    "                if os.path.isfile(\"./simple\"):\n",
    "                    os.remove(\"./simple\")\n",
    "                compile_cmd = [\"clang++\", \"simple.cpp\", \"-o\", \"simple\"]\n",
    "                if run_cmd(compile_cmd):\n",
    "                    if run_cmd([\"./simple\"]) == \"Hello\":\n",
    "                        my_compiler = [\"Linux\", \"Clang++\", [\"clang++\", f\"{filename_base}.cpp\", \"-o\", f\"{filename_base}\"]]\n",
    "        \n",
    "            if not my_compiler:\n",
    "                my_compiler=[my_platform, \"Unavailable\", []]\n",
    "    \n",
    "        elif my_platform == \"Darwin\":\n",
    "            if os.path.isfile(\"./simple\"):\n",
    "                os.remove(\"./simple\")\n",
    "            compile_cmd = [\"clang++\", \"-Ofast\", \"-std=c++17\", \"-march=armv8.5-a\", \"-mtune=apple-m1\", \"-mcpu=apple-m1\", \"-o\", \"simple\", \"simple.cpp\"]\n",
    "            if run_cmd(compile_cmd):\n",
    "                if run_cmd([\"./simple\"]) == \"Hello\":\n",
    "                    my_compiler = [\"Macintosh\", \"Clang++\", [\"clang++\", \"-Ofast\", \"-std=c++17\", \"-march=armv8.5-a\", \"-mtune=apple-m1\", \"-mcpu=apple-m1\", \"-o\", f\"{filename_base}\", f\"{filename_base}.cpp\"]]\n",
    "    \n",
    "            if not my_compiler:\n",
    "                my_compiler=[my_platform, \"Unavailable\", []]\n",
    "    except:\n",
    "        my_compiler=[my_platform, \"Unavailable\", []]\n",
    "        \n",
    "    if my_compiler:\n",
    "        return my_compiler\n",
    "    else:\n",
    "        return [\"Unknown\", \"Unavailable\", []]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f9ca2e6f-60c1-4e5f-b570-63c75b2d189b",
   "metadata": {},
   "outputs": [],
   "source": [
    "compiler_cmd = c_compiler_cmd(\"optimized\")\n",
    "\n",
    "with gr.Blocks(css=css) as ui:\n",
    "    gr.Markdown(\"## Convert code from Python to C++\")\n",
    "    with gr.Row():\n",
    "        python = gr.Textbox(label=\"Python code:\", value=python_hard, lines=10)\n",
    "        cpp = gr.Textbox(label=\"C++ code:\", lines=10)\n",
    "    with gr.Row():\n",
    "        with gr.Column():\n",
    "            sample_program = gr.Radio([\"pi\", \"python_hard\"], label=\"Sample program\", value=\"python_hard\")\n",
    "            model = gr.Dropdown([\"GPT\", \"Claude\", \"HF Inference Model\"], label=\"Select model\", value=\"GPT\")\n",
    "        with gr.Column():\n",
    "            architecture = gr.Radio([compiler_cmd[0]], label=\"Architecture\", interactive=False, value=compiler_cmd[0])\n",
    "            compiler = gr.Radio([compiler_cmd[1]], label=\"Compiler\", interactive=False, value=compiler_cmd[1])\n",
    "    with gr.Row():\n",
    "        convert = gr.Button(\"Convert code\")\n",
    "    with gr.Row():\n",
    "        python_run = gr.Button(\"Run Python\")\n",
    "        if not compiler_cmd[1] == \"Unavailable\":\n",
    "            cpp_run = gr.Button(\"Run C++\")\n",
    "        else:\n",
    "            cpp_run = gr.Button(\"No compiler to run C++\", interactive=False)\n",
    "    with gr.Row():\n",
    "        python_out = gr.TextArea(label=\"Python result:\", elem_classes=[\"python\"])\n",
    "        cpp_out = gr.TextArea(label=\"C++ result:\", elem_classes=[\"cpp\"])\n",
    "\n",
    "    sample_program.change(select_sample_program, inputs=[sample_program], outputs=[python])\n",
    "    convert.click(optimize, inputs=[python, model], outputs=[cpp])\n",
    "    python_run.click(execute_python, inputs=[python], outputs=[python_out])\n",
    "    cpp_run.click(execute_cpp, inputs=[cpp], outputs=[cpp_out])\n",
    "\n",
    "ui.launch(inbrowser=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d0ad093-425b-488e-8c3f-67f729dd9c06",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
